# -*- coding: utf-8 -*-
# @Author   : SongLiangCheng
# @QQ       : 2192383945
# @Time     : 2022/11/29 13:40
# @File     : config.py
# @Project  : scraping
# @Desc     : this is a toy
import json
import logging
import os
import re
from configparser import ConfigParser, RawConfigParser
from dataclasses import dataclass
from pathlib import Path
from urllib.parse import urlparse

import coloredlogs


def str2bool(value:str|bool) -> bool:
    if isinstance(value,bool):
        return value
    return value.lower() in ('yes','true','t','1')

@dataclass(order=True)
class Configuration:
    # 日志格式
    formatter_string: str = '%(asctime)s - %(threadName)s : {%(name)s:%(lineno)d} : %(levelname)s : %(message)s'
    # 保存的目录
    downloaddir: str = ''
    # 工作线程
    works: int = 3

    # 保存镜像的目录
    basedir: str = Path(__file__).parent.parent
    # 入口文件
    indexfile: str = 'index.html'
    # 爬取的url
    scrapy_url: str = ''
    # 公开地址
    public_domain: str = ''

    # config debug
    config_debug: bool = False

    # root debug
    debug: bool = False

    only_outline: bool = False


    def __post_init__(self) -> None:
        self.logger = logging.getLogger(__file__)
        coloredlogs.install(logger=self.logger, level=logging.INFO if not self.config_debug else  logging.DEBUG, fmt=self.formatter_string)

    def load_config_file(self, inifile_name: str) -> None:
        if not os.path.isfile(inifile_name):
            raise ValueError(f"{inifile_name} 不存在")
        self.config_ini = RawConfigParser(inline_comment_prefixes='#')
        self.config_ini.read(inifile_name,encoding='utf8')
        for field_name in self.__dataclass_fields__:
            if field_name not in dict(self.config_ini.items(section='top')).keys():
                continue
            field_value = self.config_ini.get('top',field_name)
            setattr(self, field_name, self._convert_to_type(field_name, field_value))
    def load_from_environment_variables(self) -> None:
        for field_name in self.__dataclass_fields__:
            if field_name.upper() in os.environ and os.environ[field_name.upper()] != "":
                setattr(self,field_name,self._convert_to_type(field_name,os.environ[field_name.upper()]))

    @property
    def basepath(self):
        return Path(self.basedir,self.downloaddir,self.username)
    @property
    def username(self):
        # https://www.cnblogs.com/skychen1218
        return urlparse(self.scrapy_url).path.strip('/')
    @property
    def base_domain(self):
        return f"{urlparse(self.scrapy_url).scheme}://{urlparse(self.scrapy_url).netloc}/"

    def _convert_to_type(self, field_name: str, value: str | int | bool | list[str] ) -> \
            str | int | bool | list[str] :

        if not isinstance(value,str):
            return value
        self.logger.debug(f'{value=}==>{type(getattr(self,field_name)).__name__}')
        match type(getattr(self,field_name)).__name__: #  由于实例化时，自动使用默认值，所以 定义的值类型名就是以下
            case 'str':
                return value
            case 'int':
                return int(value)
            case 'bool':
                return str2bool(value)
            case 'list':
                # 需要配置写 = 1,2,3 或 = 1 2 3
                return re.split(r'[\s,]+', value)
            # 类型不匹配时
            case _:
                raise ValueError(f'类型未实现 {getattr(self.__class__, field_name)} {value}')

    def show_config(self, style:bool=False) ->None:
        print('-'*10+'生效的配置'+'-'*10)
        for key in self.__dataclass_fields__:
            if style:
                print(f'{key.upper()}={getattr(self,key)}')
            else:
                print(f'{key=} value={getattr(self,key)}')
        print('-'*10+'生效的配置'+'-'*10)